package reaction.europarl.queries.candidates;

import java.io.IOException;

import org.apache.lucene.document.Document;

import reaction.europarl.queries.QueryEL;
import reaction.europarl.queries.features.Features;
import reaction.europarl.queries.features.TextSimilarities;
import reaction.utils.string.StringSimilarities;
import reaction.utils.string.StringUtils;


public class Candidate {

	public String entity;
	public String URL;
	public String categories;
	public String wiki_text;
	public Float lucene_score;
	public Features features;
	public double ranking_score;
	
	public Candidate() {
		super();
	}
	
	public Candidate(String entity, String URL, String categories, String wiki_text) {
		super();
		this.entity = entity;
		this.URL = URL;
		this.categories = categories;
		this.wiki_text = wiki_text;
		this.features = new Features();
	}
	
	public void extractFeatures(QueryEL q) throws IOException{		
		this.nameSimilarities(q.query_string);
		this.textualSimilarities(q);
	}
	
	public Candidate(Document doc, float lucene_score) {		
		this.entity = doc.getFieldable("entity").stringValue();
		this.URL = doc.getFieldable("URL").stringValue();
		this.categories = doc.getFieldable("categories").stringValue();
		this.wiki_text = doc.getFieldable("wiki_text").stringValue();
		this.lucene_score = lucene_score;
		this.features = new Features();
		
		
	}
	
	// Textual Similarities
	public void textualSimilarities(QueryEL q) throws IOException {
		this.features.cosine_similarity = TextSimilarities.INSTANCE.getSimilarity(q.support_doc, this.wiki_text);
		this.features.queryStringInWikiText = queryStringInWikiText(q);
		this.features.candidateNameInSupportDocument = candidateNameInSupportDocument(q);
	}
	
	// Name Similarities
	public void nameSimilarities(String query) {
		
		features.similarities = StringSimilarities.compareStrings(query,this.entity);
		features.average_similarities = features.average_similarities();		
		features.exactMatch = query.equalsIgnoreCase(entity);
		features.querySubStringOfCandidate = entity.toLowerCase().contains(query.toLowerCase());
		features.candidateSubStringOfQuery = query.toLowerCase().contains(entity.toLowerCase());		
		features.queryStartsCandidateName = query.toLowerCase().startsWith(entity.toLowerCase());
		features.queryEndsCandidateName = query.toLowerCase().endsWith(entity.toLowerCase());		
		features.candidateNameStartsQuery = query.toLowerCase().startsWith(entity);		
		features.candidateNameEndsQuery = query.toLowerCase().endsWith(entity);
		
		if (StringUtils.isUpper(query)) {	
			if (isAcroynym(query, entity)) {
				features.queryStringAcronymOfCandidate = true;
			}
			if (isAcroynym(entity, query)) {
				features.candidateAcronymOfqueryString = true;
			}	
		}
	}

	private boolean isAcroynym(String query, String name) {		
		String [] words = name.split(" ");
		char [] accro = query.toLowerCase().toCharArray();
		
		if (words.length == accro.length) {
			for (int i = 0; i < accro.length; i++) {		
				if (accro[i] != (words[i]).toLowerCase().charAt(0)) {
					return false;
				}	
			}
			return true;
		}
		return false;
	}

	public boolean queryStringInWikiText(QueryEL q){
		
		boolean nameInWikiText = this.wiki_text.toUpperCase().indexOf(q.query_string.toUpperCase()) != -1;
		
		/*
		boolean alternativeWikiText = false;
		
		for (String sense : q.alternative_names) {
			if (entity.wiki_text.toUpperCase().indexOf(sense.toUpperCase()) != -1) {
				alternativeWikiText = true;
				break;
			}
		}
		
		return (nameInWikiText || alternativeWikiText);
		*/
		
		return (nameInWikiText);
		
	}
	
	public boolean candidateNameInSupportDocument(QueryEL q) {
		//TODO: entity.name can have several tokens, suggestion:
		//TODO: try to match each token, instead of the whole string		
		return q.support_doc.toUpperCase().indexOf(entity.toUpperCase()) != -1;
	}
}
